package com.caregiver.watch.common.utils.collection;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;


/**
 * @Description: List工具
 * @Author 疆戟
 * @Date 2024/8/20 23:14
 * @Version 1.0
 */
public final class ListUtils {

    public static <T,R> List<R> map(List<T> list, Function<? super T, ? extends R> mapper) {
        if (Objects.isNull(list)) {
            return new ArrayList<>();
        }
        return list.stream().map(mapper).filter(Objects::nonNull).collect(toList());
    }

    public static <T,R> Stream<? extends R> mapStream(List<T> list, Function<? super T, ? extends R> mapper) {
        if (Objects.isNull(list)) {
            return Stream.empty();
        }
        return list.stream().filter(Objects::nonNull).map(mapper).filter(Objects::nonNull);
    }



    public static <T,R> List<R> filterMap(List<T> list, Predicate<? super T> predicate, Function<? super T, ? extends R> mapper) {
        if (Objects.isNull(list)) {
            return new ArrayList<>();
        }
        return list.stream().filter(predicate).map(mapper).filter(Objects::nonNull).collect(toList());
    }

    public static <T,R> Set<R> mapToSet(List<T> list, Function<? super T, ? extends R> mapper) {
        if (Objects.isNull(list)) {
            return new HashSet<>();
        }
        return list.stream().map(mapper).collect(toSet());
    }

    public static <T,R> List<R> mapDistinct(List<T> list, Function<? super T, ? extends R> mapper) {
        if (Objects.isNull(list)) {
            return new ArrayList<>();
        }
        return list.stream().map(mapper).filter(Objects::nonNull).distinct().collect(toList());
    }

    public static <T,R> List<R> flatMapDistinct(List<T> list, Function<? super T, ? extends Stream<? extends R>> mapper) {
        if (Objects.isNull(list)) {
            return new ArrayList<>();
        }
        return list.stream().flatMap(mapper).filter(Objects::nonNull).distinct().collect(toList());
    }

    public static <T,R> List<R> flatMap(List<T> list, Function<? super T, ? extends Stream<? extends R>> mapper) {
        if (Objects.isNull(list)) {
            return new ArrayList<>();
        }
        return list.stream().flatMap(mapper).filter(Objects::nonNull).collect(toList());
    }




    public static <K,V> Map<K, List<V>> groupingBy(List<V> list, Function<? super V, ? extends K> keyMapper) {
        if (Objects.isNull(list)) {
            return new HashMap<>();
        }
        return list.stream().collect(Collectors.groupingBy(keyMapper));
    }

    /**
     * toMap
     */
    public static <T, K> Map<K, T> toMap(List<T> list, Function<? super T, ? extends K> keyMapper) {
        return toMap(list, keyMapper, Function.identity(), (v1, v2) -> v1);
    }

    /**
     * toMap
     */
    public static <T, K, V> Map<K, V> toMap(List<T> list, Function<? super T, ? extends K> keyMapper,
                                            Function<? super T, ? extends V> valueMapper) {
        return toMap(list, keyMapper, valueMapper, (v1, v2) -> v1);
    }

    /**
     * toMap
     */
    public static <T, K, V> Map<K, V> toMap(List<T> list, Function<? super T, ? extends K> keyMapper,
                                            Function<? super T, ? extends V> valueMapper,
                                            BinaryOperator<V> mergeFunction) {
        if (CollectionUtils.isEmpty(list)) {
            return new HashMap<>();
        }
        return list.stream().collect(Collectors.toMap(keyMapper, valueMapper, mergeFunction));
    }

    /**
     * filter
     */
    public static <T> List<T> filter(List<T> list, Predicate<? super T> predicate) {
        if (Objects.isNull(list)) {
            return new ArrayList<>();
        }
        return list.stream().filter(predicate).collect(toList());
    }

    /**
     * ofNullable
     */
    public static <T> Stream<T> ofNullable(List<T> source, Stream<T> defaultValue) {
        return CollectionUtils.isEmpty(source) ? defaultValue : source.stream();
    }

    /**
     * ofNullable
     */
    public static <T> List<T> ofNullable(List<T> source, List<T> defaultValue) {
        return CollectionUtils.isEmpty(source) ? defaultValue : source;
    }



    /**
     * 分割集合
     * @param list
     * @param size
     * @return
     */
    public static <T> List<List<T>> partition(List<T> list, int size) {
        if (Objects.isNull(list)) {
            return new ArrayList<>();
        }
        return org.apache.commons.collections4.ListUtils.partition(list, size);
    }


    /**
     * join
     */
    public static <T>  String join(List<T> list, String separator) {
        if (CollectionUtils.isEmpty(list)) {
            return StringUtils.EMPTY;
        }
        return list.stream().map(String::valueOf).collect(Collectors.joining(separator));
    }

    /**
     * anyMatch
     */
    public static <T> boolean anyMatch(List<T> list, Predicate<? super T> predicate) {
        if (Objects.isNull(list)) {
            return false;
        }
        return list.stream().anyMatch(predicate);
    }
}
